package com.alks.function.service.finance.attend;

import com.alks.entity.data.entity.PcEmpAttend;
import com.alks.entity.data.entity.SyncSignData;
import com.alks.entity.data.entity.SyncWorkerInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.config.ProfileConfig;
import com.alks.function.mapper.finance.attend.SyncVNMDataMapper;
import com.alks.function.service.administration.PcEmpAttendService;
import jodd.util.StringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: chen
 * @date: 2025/2/24
 * @description: 考勤计算
 */
@Service
public class AttendanceCalculateService {

    @Resource
    private SyncVNMDataMapper syncVNMDataMapper;
    @Resource
    private PcEmpAttendService pcEmpAttendService;

    // 定义日期时间格式
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    DateTimeFormatter formatterDate = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Resource
    private ProfileConfig profileConfig;

    @Scheduled(cron = "0 0 1 * * *")
    public void dailySync() {
        if (!profileConfig.isVNMProfile()) {
            return;
        }
        LocalDateTime yesterday = LocalDateTime.now().plusDays(-1);
        syncAttendData(yesterday.format(formatterDate), yesterday.format(formatterDate));
    }

    public String syncAttendData(String beginDate, String endDate) {
        if (!profileConfig.isVNMProfile()) {
            return "当前环境不执行同步";
        }
        if (StringUtil.isEmpty(beginDate) || StringUtil.isEmpty(endDate)) {
            beginDate = LocalDate.now().plusDays(-1).format(formatterDate);
            endDate = beginDate;
        } else {
            try {
                LocalDate begin = LocalDate.parse(beginDate, formatterDate);
                LocalDate end = LocalDate.parse(endDate, formatterDate);
                if (begin.isAfter(end)) {
                    return "开始时间不能大于结束时间";
                }
                if (end.isEqual(LocalDate.now())) {
                    return "当天数据需次日才可同步";
                }
            } catch (Exception e) {
                throw new ServiceErrorException("参数格式错误");
            }
        }

        List<SyncSignData> signDataList = syncVNMDataMapper.querySignData(beginDate, endDate);
        if (signDataList.isEmpty()) {
            return "暂无数据需要同步";
        }
        // 查询员工信息
        List<SyncWorkerInfo> workerList = syncVNMDataMapper.getAllWorker();
        Map<String, SyncWorkerInfo> workerInfoMap = workerList.stream().collect(Collectors.toMap(SyncWorkerInfo::getSignCode, v -> v));

        List<PcEmpAttend> recordList = new ArrayList<>();
        Map<String, List<SyncSignData>> groupByDate = signDataList.stream().collect(Collectors.groupingBy(SyncSignData::getDate));
        for (String date : groupByDate.keySet()) {
            List<SyncSignData> list = groupByDate.get(date);
            if (list.isEmpty()) continue;
            Map<String, List<SyncSignData>> groupByWorker = list.stream().collect(Collectors.groupingBy(SyncSignData::getSignCode));
            for (Map.Entry<String, List<SyncSignData>> entry : groupByWorker.entrySet()) {
                List<LocalTime> punchTimes = entry.getValue().stream().map(e ->  LocalDateTime.parse(e.getTime(), formatter).toLocalTime()).collect(Collectors.toList());
                PcEmpAttend empAttend = new PcEmpAttend();
                empAttend.setCompanyId("RY");
                empAttend.setWorkerId(workerInfoMap.get(entry.getKey()).getWorkerNo());
                empAttend.setWorkerName(workerInfoMap.get(entry.getKey()).getWorkerName());
                empAttend.setDdate(LocalDateTime.parse(date, formatter).toLocalDate());
                if (punchTimes.isEmpty()) {
                    continue;
                }
                calculateAttendance(punchTimes, empAttend);
                recordList.add(empAttend);
            }
        }
        return pcEmpAttendService.batchInsert(recordList);
    }

    /**
     * 统计考勤记录
     * @param punchTimes
     * @param empAttend
     */
    public static void calculateAttendance(List<LocalTime> punchTimes, PcEmpAttend empAttend) {
        if (punchTimes.size() < 2) {
            LocalTime signTime = punchTimes.get(0);
            int signMinutes = signTime.getHour() * 60 + signTime.getMinute();
            if (signMinutes < 720) {
                empAttend.setRemark("下午缺卡");
            } else {
                empAttend.setRemark("上午缺卡");
            }
            return;
        }

        // 排序打卡时间，取最早和最晚作为上班和下班时间
        Collections.sort(punchTimes);
        LocalTime start = punchTimes.get(0);
        LocalTime end = punchTimes.get(punchTimes.size() - 1);

        // 转换为分钟数
        int startMinutes = start.getHour() * 60 + start.getMinute();
        int endMinutes = end.getHour() * 60 + end.getMinute();

        // 判断是否需要扣除午休
        boolean deductLunch = startMinutes <= 720 && endMinutes >= 780;

        // 计算总工作时间（扣除午休）
        int totalWorkMinutes = endMinutes - startMinutes - (deductLunch ? 60 : 0);
        totalWorkMinutes = Math.max(totalWorkMinutes, 0);

        empAttend.setLateMinutes(BigDecimal.valueOf(Math.max(startMinutes - 450, 0)));
        if (empAttend.getLateMinutes().compareTo(BigDecimal.ZERO) != 0) {
            empAttend.setLateNums(BigDecimal.ONE);
        } else {
            empAttend.setLateNums(BigDecimal.ZERO);
        }
        empAttend.setEarlyMinutes(BigDecimal.valueOf(Math.max(990 - endMinutes, 0)));
        if (empAttend.getEarlyMinutes().compareTo(BigDecimal.ZERO) != 0) {
            empAttend.setEarlyNums(BigDecimal.ONE);
        } else {
            empAttend.setEarlyNums(BigDecimal.ZERO);
        }

        // 计算正班时间（上午和下午段）
        int morningStart = Math.max(startMinutes, 450);  // 7:30
        int morningEnd = Math.min(endMinutes, 690);      // 11:30
        int morningMinutes = Math.max(morningEnd - morningStart, 0);

        int afternoonStart = Math.max(startMinutes, 750); // 12:30
        int afternoonEnd = Math.min(endMinutes, 990);     // 16:30
        int afternoonMinutes = Math.max(afternoonEnd - afternoonStart, 0);

        int regularMinutes = morningMinutes + afternoonMinutes;

        // 计算加班时间（按半小时向上取整）
        int overtimeMinutes = totalWorkMinutes - regularMinutes;
        overtimeMinutes = Math.max(overtimeMinutes, 0);

        // 转换为半小时单位
        int halfHours = overtimeMinutes / 30;
        double overtimeHours = halfHours * 0.5;

        // 正班时长（小时）
        double regularHours = regularMinutes / 60.0;

        regularHours = regularHours > 8 ? 8 : regularHours;

        empAttend.setWorkHours(BigDecimal.valueOf(regularHours));
        empAttend.setOverHours(BigDecimal.valueOf(overtimeHours));

        if (empAttend.getOverHours().compareTo(BigDecimal.ZERO) != 0) {
            empAttend.setOverNums(BigDecimal.ONE);
        } else {
            empAttend.setOverNums(BigDecimal.ZERO);
        }
    }
}
